var Kanas = {

    version : '1.0.1',
    versionDetail : {
        major : 1,
        minor : 0,
        patch : 0
    },
    browserLanguage: (function(){
    	return navigator.browserLanguage?navigator.browserLanguage:navigator.language;
    })(),
	Browser: (function(){
		var ua = navigator.userAgent;
		var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
		return {
			IE:             !!window.attachEvent && !isOpera,
			Opera:          isOpera,
			WebKit:         ua.indexOf('AppleWebKit/') > -1,
			Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
			MobileSafari:   /Apple.*Mobile/.test(ua)
		};
	})(),
	isArray: function(v){
    	return Object.prototype.toString.apply(v) === '[object Array]';
  	},
  	exec: function(func,args){
  		if(Kanas.isArray(args))	func.apply(this,args);
		else func.call(this,args);
  	},
	getRequest:function(para){
		var url = location.href;
		var paraString = url.substring(url.indexOf("?")+1,url.length).split("&"); 
		var paraObj = {};
		var k;
		var v;
		var j;
		for (var n=0; j=paraString[n]; n++){
			k = j.substring(0,j.indexOf("="));
			v = j.substring(j.indexOf("=")+1,j.length);
			if(!paraObj[k])
				paraObj[k] = v;
			else{
				if(this.isArray(paraObj[k]))
					paraObj[k][paraObj[k].length] = v;
				else
					paraObj[k]=[paraObj[k],v];
			}
		}
		return paraObj[para];
	},
	
	// utility function to retrieve an expiration data in proper format;
    getExpDate:function(days, hours, minutes){
        var expDate = new Date();
        if(typeof(days) == "number" && typeof(hours) == "number" && typeof(hours) == "number"){
            expDate.setDate(expDate.getDate() + parseInt(days));
            expDate.setHours(expDate.getHours() + parseInt(hours));
            expDate.setMinutes(expDate.getMinutes() + parseInt(minutes));
            return expDate.toGMTString();
        }
    },

    // utility function called by getCookie()
    _getCookieVal:function(offset){
        var endstr = document.cookie.indexOf(";", offset);
        if(endstr == -1){
            endstr = document.cookie.length;
        }
        return unescape(document.cookie.substring(offset, endstr));
    },

    // function to retrieve cookie by name
    getCookie:function(name){
        var arg = name + "=";
        var alen = arg.length;
        var clen = document.cookie.length;
        var i = 0;
        while(i < clen){
            var j = i + alen;
            if (document.cookie.substring(i, j) == arg)
                return this._getCookieVal(j);
            i = document.cookie.indexOf(" ", i) + 1;
            if(i == 0) break;
        }
        return;
    },

    // store cookie value with optional details as needed
    setCookie:function(name, value, expires, path, domain, secure){
        document.cookie = name + "=" + escape(value) +
            ((expires) ? "; expires=" + expires : "") +
            ((path) ? "; path=" + path : "") +
            ((domain) ? "; domain=" + domain : "") +
            ((secure) ? "; secure" : "");
    },

    // remove the cookie by setting ancient expiration date
    deleteCookie:function(name,path,domain){
        if(getCookie(name)){
            document.cookie = name + "=" +
                ((path) ? "; path=" + path : "") +
                ((domain) ? "; domain=" + domain : "") +
                "; expires=Thu, 01-Jan-70 00:00:01 GMT";
        }
    }
};

Kanas.langKey = "lang";
Kanas.getLang = function(){
	var lang = Kanas.getRequest(Kanas.langKey);
	if(lang){
		Kanas.setCookie(Kanas.langKey, lang, -1);
		return lang;
	}
	return Kanas.clientLanguage;
};

Kanas.clientLanguage=(function(){
	var lang = Kanas.getCookie(Kanas.langKey);
	if(lang) return lang;
	return Kanas.browserLanguage;
})();

Kanas.ArrayHelper={
	contains:function(array,value){
		for(var k in array)if(array[k]==value)return true;
		return false;
	}
};


Kanas.MapHelper={
	containsValue:function(map,value){
		for(var k in map)if(map[k]==value)return true;
		return false;
	},
	key:function(map,value){
		for(var k in map)if(map[k]==value)return k;
		return null;
	}
};

/**
 * script loader
 *
 */

Kanas.ScriptLoader={
	initFlag:false,
	scriptContext:[],
	existScript:function(strURI){
		if(!Kanas.ScriptLoader.initFlag){
			var eleHead=document.getElementsByTagName("head")[0];
			for (var k in eleHead.childNodes){
				if(eleHead.childNodes[k].tagName && 
					eleHead.childNodes[k].tagName.toLowerCase()=="script" )
				Kanas.ScriptLoader.scriptContext.push(eleHead.childNodes[k].src);
			}
			Kanas.ScriptLoader.initFlag=true;
		}
		return Kanas.ArrayHelper.contains(Kanas.ScriptLoader.scriptContext, strURI);
	},
	/*
	option:
		onComplete: callback function while script loaded.
		args: parameters for completion callback function, array or value.
	*/
	batchLoad:function(arrayURI,option){
		if((!arrayURI)||arrayURI.length==0){
			if(option&&option.onComplete){
				if(Kanas.isArray(option.args))
					eval(option.onComplete).apply(this,option.args);
				else eval(option.onComplete).call(this,option.args);
			}
			return;
		}
		if(!option)option={};
		if(!option.seed) option.seed=0;
		var strURI=arrayURI[option.seed];
		if(Kanas.ScriptLoader.existScript(strURI)){
			option.seed++;
			if(option.seed>=arrayURI.length){
				if(option.onComplete){
					if(Kanas.isArray(option.args))
						eval(option.onComplete).apply(this,option.args);
					else eval(option.onComplete).call(this,option.args);
				}
			}else Kanas.ScriptLoader.batchLoad(arrayURI,option);
			return;
		}
		var element = document.createElement("script");
        element.src = strURI;
        element.type = 'text/javascript';
        element.language = 'javascript';
        
        if (Kanas.Browser.IE) {
			element.onreadystatechange = function() {
				var state = this.readyState;
				if (state == "loaded" || state == "interactive" || state == "complete") {
					this.onreadystatechange = null;
					Kanas.ScriptLoader.scriptContext.push(strURI);
					option.seed++;
					if(option.seed>=arrayURI.length){
						if(option.onComplete){
							if(Kanas.isArray(option.args))
								eval(option.onComplete).apply(this,option.args);
							else eval(option.onComplete).call(this,option.args);
						}
					}else Kanas.ScriptLoader.batchLoad(arrayURI,option);
				}
			};
        } else if (Kanas.Browser.Gecko || Kanas.Browser.WebKit || true) {
			element.onload = function() {
				element.onload = null;
				Kanas.ScriptLoader.scriptContext.push(strURI);
				option.seed++;
				if(option.seed>=arrayURI.length){
					if(option.onComplete){
						if(Kanas.isArray(option.args))
							eval(option.onComplete).apply(this,option.args);
						else eval(option.onComplete).call(this,option.args);
					}
				}else Kanas.ScriptLoader.batchLoad(arrayURI,option);
			};
        }
        document.getElementsByTagName("head")[0].appendChild(element);	
	},
	
	loadStyle:function(styleUrl){
		if(styleUrl){
			var cssfiles = document.getElementsByTagName('link');
			var cssfile;
			for (var t=0,l=cssfiles.length;t<l;t++){
				cssfile = cssfiles.item(t);
				if(cssfile.rel == 'stylesheet'&&cssfile.href==styleUrl)return;
			}
			var head = document.getElementsByTagName('head').item(0);
			var css = document.createElement('link');
			css.href = styleUrl;
			css.rel = 'stylesheet';
			css.type = 'text/css';
			head.appendChild(css);
			return;
		}
	}
};

Kanas.DomHelper={
	switchView:function(){
		var v=null;
		var o=arguments;
		o=Array.prototype.slice.call(arguments,0);
		for(var key in o){
			if(!v)v=o[key];
			if(o[key].style.display!='none'&&o[parseInt(key)+1]){
				v=o[key+1];
			}
			o[key].style.display='none';
		}
		if(v)v.style.display='';
	},
	appendAttr:function(domid,attr,value){
		var v = dojo.attr(domid,attr);
		if(!v)v="";
		return dojo.attr(domid,attr,v+value);
	},
	appendDojoProp:function(domid,key,value){
		if(key!=undefined&&value!=undefined){
			var prop = dojo.attr(domid,"data-dojo-props");
			this.appendAttr(domid, "data-dojo-props", ((prop)?",":"")+key+":'"+value.replace(/'/g,"\\'")+"'");
		}
	}
};

Kanas.App={
	_moduleKeyName:"{moduleId}",
	_moduleBase:"",
	_moduleUrl:"kanas/module/{moduleId}",
	_modules:{},
	_loadModuleScript:function(module,params,option){
		if(module.styleResources&&dojo.string.trim(module.styleResources)!=""){
			var arr=dojo.string.trim(module.styleResources).split(',');
			for(var key in arr){
				Kanas.ScriptLoader.loadStyle(Kanas.tools.burl(Kanas.App._moduleBase, arr[key]));
			}
		}
		if(module.codeResources&&dojo.string.trim(module.codeResources)!=""){
			var arr=dojo.string.trim(module.codeResources).split(',');
			var options={onComplete:Kanas.App._loadModuleView,args:[module,params,option]};
			for(var key in arr)arr[key]=Kanas.tools.burl(Kanas.App._moduleBase,arr[key]);
			Kanas.ScriptLoader.batchLoad(arr,options);
		}else{
			Kanas.App._loadModuleView(module,params,option);
		}
	},
	_loadModuleView:function(module,params,option){
		if((!module.pageURI)||dojo.string.trim(module.pageURI)=="")return;
		if(!option)return;
		if(option.closable==undefined)option.closable=true;
		var moduleurl=module.pageURI;
		var modulename=Kanas.App.bundleResource(option.i18nResource,module.id,option.i18nParams);
		if(module.name&&modulename==module.id)modulename=module.name;
		var regEx;
		if(params){
			for(var p in params){
				regEx=new RegExp( "{"+p+ "}", "gi"); 
				moduleurl=moduleurl.replace(regEx,params[p]);
				modulename=modulename.replace("{title}",option.title);
			}
		}
		Kanas.ui.loadDojoExt({
			url:moduleurl,
			target:option.target,
			title:modulename,
			showOn:module.showOn,
			closable:option.closable,
			refreshOnShow:false,
			iconClass:module.iconClassS,
			executeScripts:true,
			kanasType:'module'
		});
	},
	init:function(base,murl){
		Kanas.App._moduleBase=base;
		Kanas.App._moduleUrl=murl;
	},
	loadModuleConfig:function(mid,callback,params,option){
		if(Kanas.App._modules[mid])callback.call(null,Kanas.App._modules[mid],params,option);
		else dojo.xhrGet({
			url:Kanas.App._moduleUrl.replace(Kanas.App._moduleKeyName,mid),
			handleAs:"json",
			load:function(response){
				if(response.id){
					Kanas.App._modules[response.id]=response;
					callback.call(null,response,params,option);
				}
			}
		});
	},
	openModule:function(moduleId,params,option){
		Kanas.App.loadModuleConfig(moduleId,Kanas.App._loadModuleScript,params,option);
	},
	parentModule:function(moduleId,params,option){
		window.parent.$ka.openModule(moduleId,params,option);
	},
	bundleResource:function(resource,str,params,defaultValue){
		if(!resource)return str;
		var r = resource[str];
		if(!r){
			if(defaultValue)return defaultValue;
			else return str;
		}
		return $ksub(r,params);
	},
	/**
	 * To resolve ie script issue while unloading the window.
	 */
	clearBeforeIEUnload:function(){
		if(Kanas.Browser.IE)
			dojo.connect("onbeforeunload",function(){document.body.innerHTML="";});
	},
	loading:function(exp){
		if(Kanas.Browser.IE) setTimeout(exp,1);
		else eval(exp);
	}
};


Kanas.tools={
	aurl:function(relativeUrl,baseUrl) {
		if(relativeUrl.substring(0,4)=="http")return relativeUrl;
	    if (baseUrl == null || baseUrl.length <= 0)
	        baseUrl = location.href;
	    var dt = baseUrl.split("?")[0].split("/");
	    dt.length--;
	    while (relativeUrl.indexOf("../") == 0) {
	        relativeUrl = relativeUrl.slice(3);
	        dt.length--;
	    }
	    return unescape(dt.join("/") + "/" + relativeUrl);
	},
	burl:function(base,url) {
		if(!url)return;
		if(url.substring(0,1)=="/")return base+url;
		return url;
	},
	escapeBlank:function(value){
		return (value&&dojo.string.trim(value+"")!="")?value:"&nbsp;";
	},
	substitue:function(str,array){
		if(!str)return "";
		else return dojo.string.substitute(str,array);
	}
};


/**kanas UI utils**/

Kanas.ui={
	_formatUrl:function(url){
		return $kt.aurl(url).toLowerCase();
	},
	_getExtChild:function(container,url){
		if(!container.kanasMap)container.kanasMap={};
		var child=Kanas.MapHelper.key(container.kanasMap,url);
		if(child){
			return dijit.byId(child);
		}
		else return null;
	},
	_addExtChild:function(container,child,url){
		if(!container.kanasMap)container.kanasMap={};
		container.kanasMap[child.get('id')]=url;
	},
	_closeExtChild:function(container,url){
		var child=Kanas.ui._getExtChild(container,url);
		if(child){
			if(container.removeChild){
				container.removeChild(child);
			}
			Kanas.ui._removeChildKey(container,child);
			child.destroyRecursive(false);
		}
	},
	_removeChildKey:function(container,child){
		if(!container.kanasMap)return;
		delete container.kanasMap[child.get('id')];
	},
	destroyExtChild:function(container,child){
		if(typeof container==="string")container=dijit.byId(container);
		if(typeof child==="string")child=dijit.byId(child);
		if(child){
			if(container.removeChild){
				container.removeChild(child);
			}
			Kanas.ui._removeChildKey(container,child);
			child.destroyRecursive(false);
		}
	},
	loadKanasExt:function(option){
		if(!option.url)option.url=dojo.attr(option.fireNode,"href");
		if(!option.target)option.target=dojo.attr(option.fireNode,"target");
		if(!option.title)option.title=dojo.attr(option.fireNode,"title");
		var c=option.fireNode.parentNode;
		while((!dojo.attr(c,'data-kanas-type')||dojo.attr(c,'data-kanas-type')!="module")&&(c.parentNode!=document.body)){
			c=c.parentNode;
		}
		var exts=dojo.query("[data-kanas-id='"+option.target+"']",c);
		if(exts.length>0&&exts[0].id){
			var ext=dijit.byId(exts[0].id);
			var child=Kanas.ui._getExtChild(ext,option.url);
			if(!child){
				var p=new dojox.layout.ContentPane({title:option.title,closable:true,
					refreshOnShow:false,
					executeScripts:true,
					href:option.url
					});
				if(ext.addChild){
					ext.addChild(p);
					if(ext.selectChild)ext.selectChild(p);
					Kanas.ui._addExtChild(ext,p,option.url);
					p.onClose=function(){
						Kanas.ui._removeChildKey(ext,p);
						return true;
					};
				}else if(ext.set){
					ext.set('content',p);
				}
			}else{
				if(ext.selectChild){
					ext.selectChild(child);
				}
			}
		}
	},
	/**
	 * opt/option, the parameters for extension loader,
	 * 		href/url: the module url
	 * 		target: the loader container id
	 * 		region: the region of BorderContainer
	 * 		title: module title
	 * 		showOn: show mode, 'iframe' or others
	 * 		closable: indicate this module can be closed or not
	 * 		refreshOnShow: refresh on show
	 * 		iconClass: module icon
	 *      splitter: splitter of BorderContainer
	 * 		style: css style
	 * 		executeScripts: execute scripts or not
	 * 		kanasType: the kanas type for this module
	 * 		fireNode: event trigger
	 * 		withoutParams: boolean, save URL without parameters, default true when load in-line, false when iframe
	 * 		reload: true will reload the page if the module was loaded. default false; 
	 * 		key: used for identifing a extension;
	 * 		container: child container
	 */
	loadDojoExt:function(opt){
		var option = {};
		for(var key in opt)option[key]=opt[key];
		option.href=(option.href?option.href:(option.url?option.url:dojo.attr(option.fireNode,"href")));
		if(!option.target)option.target=dojo.attr(option.fireNode,"target");
		if(option.fireNode){
			if(!option.title)option.title=dojo.attr(option.fireNode,"title");
			if(!option.key)option.key=dojo.attr(option.fireNode,"key");
		}
		if(option.executeScripts==undefined||option.executeScripts==null)option.executeScripts=true;
		var ext=dijit.byId(option.target);
		var keyurl;
		if(option.key)
			keyurl=option.key;
		else{
			keyurl=Kanas.ui._formatUrl(option.href);
			if(option.withoutParams)
				keyurl=(keyurl.indexOf('?')==-1)?keyurl:
					keyurl.substring(0,keyurl.indexOf('?'));
			}
		if(option.showOn&&option.showOn=='iframe'){
			if(option.withoutParams==undefined||option.withoutParams==null)
				option.withoutParams=false;}
		else{
			if(option.withoutParams==undefined||option.withoutParams==null)
				option.withoutParams=true;}
		if(option.withoutParams)
			keyurl=(keyurl.indexOf('?')==-1)?keyurl:
				keyurl.substring(0,keyurl.indexOf('?'));
		
		var child=Kanas.ui._getExtChild(ext,keyurl);
		if(child&&option.reload){
			child=null;
			Kanas.ui._closeExtChild(ext, keyurl);
		}
		if(!child){
			var p;
			if(option.showOn&&option.showOn=='iframe'){
				if(!option.container)p=new dijit.layout.ContentPane(option);
				else p=new option.container(option);
				p.set('style','padding:0px');
				p.set('content','<iframe src="'+option.href+'" frameborder="0" width="100%" height="100%"></iframe>');
			}else{
				if(!option.container)p=new dojox.layout.ContentPane(option);
				else p=new option.container(option);
			}
			if(ext.addChild){
				ext.addChild(p);
				if(ext.selectChild)ext.selectChild(p);
				Kanas.ui._addExtChild(ext,p,keyurl);
				p.onClose=function(){
					Kanas.ui._removeChildKey(ext,p);
					return true;
				};
			}else if(ext.set){
				ext.set('content',p);
			}
			if(option.kanasType)dojo.attr(p.domNode,'data-kanas-type','module');
		}else{
			if(ext.selectChild){
				ext.selectChild(child);
			}
		}
	},
	clickLoadDojoExt:function(obj){
		if(obj.srcElement||(obj.target&&typeof(obj.target)!="string"))
			obj=dojo.fixEvent(obj).target;
		Kanas.ui.loadDojoExt({fireNode:obj,closable:true});
	},
	/**
	 * 		url: the module url
	 * 		target: the loader container id
	 */
	unloadDojoExt:function(target,url){
		var container=dijit.byId(target);
		url=Kanas.ui._formatUrl(url);
		Kanas.ui._closeExtChild(container, url);
	},
	
	timeoutDialog:function(content,delay,title,style,thenfn){
		var dlg = new dijit.Dialog({
			title: title?title:"Notice",
			content:content,
			closable:false,
			style:"background-color:#FFFFFF;"
		});
		if(style)dlg.set("style",style);
		dlg.show();
		setTimeout(function(){
			if(dlg){
				dlg.hide();
				dlg.destroyRecursive(false);
			}
			if(thenfn)thenfn.call();
		},delay);
	},
	
	/**
	 * option
	 * 	id,url,style,title,caller
	 */
	topDialog:function(option){
		var top = window;
		while(top != window.parent){
			top = window.parent;
		};
		option.caller = window;
		top.Kanas.ui.showDialog(option);
	},
	
	/**
	 * option
	 * 	id,href/url,style,title,caller
	 */
	showDialog:function(option){
		option.href=(option.href?option.href:option.url);
		var dlg = null;
		if(option.id) dlg = dijit.byId(option.id);
		if(dlg){
			dlg.destroyDescendants(false);
			dlg.set("href",option.href);
		}else{
			dlg = new dojox.widget.DialogSimple({
				id:option.id,
				title: option.title?option.title:"Notice",
				style: "padding:0px;background-color:#FFFFFF;",
				doLayout:false,
				executeScripts:true,
				href:option.href
			});
		}
		if(option.style)dlg.set("style",option.style);
		dlg.caller = option.caller;
		dlg.resource = option.resource;
		dlg.show();
		return dlg;
	},
	
	setUniqueClass:function(domNode,clsNm){
		dojo.query("."+clsNm).removeClass(clsNm);
		dojo.addClass(domNode,clsNm);
	},
	
	/**
	 * query a single widget by using css selector under the specified dom.
	 */
	qw:function(expression,domNode){
		var d = dojo.query(expression,domNode);
		if(d[0]){
			return dijit.byId(dojo.attr(d[0],"widgetid"));
		}else
			return null;
	}
};
Kanas.dojo={
	require:function(clz){
		try{
			var c = eval(clz);
			if(!c)dojo.require(clz);
		}catch(err){
			dojo.require(clz);
		}
	}
};

/*short cuts*/
$k=Kanas;
$ka=Kanas.App;
$ki18n=Kanas.App.bundleResource;
$kt=Kanas.tools;
$ku=Kanas.ui;
$kdom=Kanas.DomHelper;
$ksub=Kanas.tools.substitue;
$kdj=Kanas.dojo;
